package parser

import (
	_ "embed"
	"fmt"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

// Project 项目
type Project struct {
	Path        string   `json:"path,omitempty" yaml:"path,omitempty"`                 //当前路径
	Files       []*File  `json:"files,omitempty" yaml:"files,omitempty"`               //文件
	UsedImports []Import `json:"used_imports,omitempty" yaml:"used_imports,omitempty"` //使用的导入
	Module      Module   `json:"module,omitempty" yaml:"module,omitempty"`             //模块

	Imports []Import `json:"imports,omitempty" yaml:"imports,omitempty"` //使用的导入
}

type Import struct {
	Alias   string
	Package string
}

func (ipt Import) String() string {
	if ipt.Alias == "" || ipt.Alias == filepath.Base(ipt.Package) {
		return strconv.Quote(ipt.Package)
	} else {
		return fmt.Sprintf("%s %q", ipt.Alias, ipt.Package)
	}
}

type Module struct {
	Package string `json:"package,omitempty" yaml:"package,omitempty"` //包名
	Path    string `json:"path,omitempty" yaml:"path,omitempty"`       //模块路径
}

// File 文件
type File struct {
	Package   string            `json:"package,omitempty" yaml:"package,omitempty"`     //模块名
	Imports   map[string]string `json:"imports,omitempty" yaml:"imports,omitempty"`     //导入
	Functions []*Function       `json:"functions,omitempty" yaml:"functions,omitempty"` //方法集合

	prj *Project
}

// Function 方法
type Function struct {
	Package    string   `json:"package,omitempty" yaml:"package,omitempty"`         //全名
	Type       Type     `json:"type,omitempty" yaml:"type,omitempty"`               //方法名
	Router     string   `json:"router,omitempty" yaml:"router,omitempty"`           //路由
	HasContext bool     `json:"has_context,omitempty" yaml:"has_context,omitempty"` //内容
	Input      []*Param `json:"input,omitempty" yaml:"input,omitempty"`             //输入参数
	Output     []*Param `json:"output,omitempty" yaml:"output,omitempty"`           //输出参数
	Method     []string `json:"method,omitempty" yaml:"method,omitempty"`           //请求方法
	Comment    []string `json:"comment,omitempty" yaml:"comment,omitempty"`         //注释

	file *File
}

func (fun Function) Handler() string {
	return strings.NewReplacer(".", "__", "/", "__").Replace(fun.Package)
}

// Param 参数
type Param struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"` //参数名
	Type Type   `json:"type,omitempty" yaml:"type,omitempty"` //参数类型
	Ptr  int    `json:"ptr,omitempty" yaml:"ptr,omitempty"`   //是否指针

	file *File
}

func (p Param) String() string {
	return strings.TrimSpace(fmt.Sprintf("%s %s%s", p.Name, strings.Repeat("*", p.Ptr), p.Type.String()))
}

type Type struct {
	Package string `json:"package,omitempty" yaml:"package,omitempty"`
	Sel     string `json:"sel,omitempty" yaml:"sel,omitempty"`
	Name    string `json:"name,omitempty" yaml:"name,omitempty"`

	file *File
}

func (t Type) IsExported() bool {
	ch, _ := utf8.DecodeRuneInString(t.Name)
	return unicode.IsUpper(ch)
}

func (t Type) IsContext() bool {
	return t.Package == "context" && t.Name == "Context"
}

func (t Type) IsError() bool {
	return t.Package == "" && t.Name == "error"
}

func (t Type) String() string {
	var n string
	if t.Sel != "" {
		n = t.Sel + "." + t.Name
	} else {
		n = t.Name
	}
	return n
}
